#include "wms_http.h"
#include "wms_printer.h"
#include "wms_device.h"
#include "wms_wifi.h"
#include "wms_hal.h"  // 添加硬件抽象层头文件
#include <ArduinoJson.h>  // 添加JSON处理库

#define HTTP_SERVER_PORT 80

static WebServer server(HTTP_SERVER_PORT);
static http_server_state_e http_server_status = HTTP_SERVER_STOPPED;
static device_bind_state_e http_device_bind_state = DEVICE_UNBINDED;

static char server_url[100] = {0};
static char device_id[32] = {0};

static unsigned long last_heartbeat_time = 0;

// 定义打印图片的处理函数
void handlePrintImage();
// 定义设备绑定的处理函数
void handleDeviceBinding();
// 定义处理不存在路径的函数
void handleNotFound();
// 定义Base64解码辅助函数
int base64_decoded_length(const char* encoded);
void base64_decode(const char* encoded, uint8_t* decoded);



// 初始化HTTP服务器
void init_http_server() {
    strcpy(device_id, "MINI_PRINTER_"); // 设备ID前缀
    String mac = WiFi.macAddress();
    mac.replace(":", "");
    strcat(device_id, mac.substring(6).c_str()); // 使用MAC地址后6位作为设备标识
    
    // 设置处理函数
    server.on("/print", HTTP_POST, handlePrintImage);
    server.on("/bind", HTTP_POST, handleDeviceBinding);
    server.onNotFound(handleNotFound);
    
    // 启动服务器
    server.begin();
    http_server_status = HTTP_SERVER_RUNNING;
    Serial.println("HTTP服务器已启动");
    Serial.print("设备ID: ");
    Serial.println(device_id);
}

// 启动HTTP服务器
void start_http_server() {
    if (WifiManager.isConnected()) {
        server.begin();
        http_server_status = HTTP_SERVER_RUNNING;
        Serial.println("HTTP服务器已启动");
    } else {
        Serial.println("WiFi未连接，无法启动HTTP服务器");
    }
}

// 停止HTTP服务器
void stop_http_server() {
    if (http_server_status == HTTP_SERVER_RUNNING) {
        server.stop();
        http_server_status = HTTP_SERVER_STOPPED;
        Serial.println("HTTP服务器已停止");
    }
}

// 处理HTTP请求
void handle_http_requests() {
    if (http_server_status == HTTP_SERVER_RUNNING) {
        server.handleClient();
    }
}

// 获取HTTP服务器状态
http_server_state_e get_http_server_status() {
    return http_server_status;
}

// 发送心跳包
bool send_heartbeat(const char* server_url) {
    if (http_device_bind_state != DEVICE_BINDED || !WifiManager.isConnected()) {
        Serial.println("设备未绑定或WiFi未连接，无法发送心跳包");
        return false;
    }

    if (server_url == NULL || strlen(server_url) == 0) {
        Serial.println("服务器URL为空，无法发送心跳包");
        
        // 尝试从全局设备状态获取服务器URL
        device_state_t *pdevice = get_device_state();
        if (strlen(pdevice->server_url) > 0) {
            Serial.println("从全局设备状态获取服务器URL");
            server_url = pdevice->server_url;
        } else {
            return false;
        }
    }

    // 检查并修正URL格式
    String url = String(server_url);
    if (!url.startsWith("http://") && !url.startsWith("https://")) {
        Serial.println("URL格式错误，自动添加http://前缀");
        url = "http://" + url;
    }
    
    Serial.print("发送心跳包，服务器URL: ");
    Serial.println(url);
    
    HTTPClient http;
    String apiUrl = url + "/api/printer/heartbeat/";
    
    Serial.print("发送心跳包到URL: ");
    Serial.println(apiUrl);
    
    bool beginResult = http.begin(apiUrl);
    if (!beginResult) {
        Serial.println("HTTP客户端初始化失败");
        return false;
    }
    
    http.addHeader("Content-Type", "application/json");
    
    // 获取设备ID
    const char* device_id_to_use = device_id;
    if (strlen(device_id) == 0) {
        // 如果模块内的设备ID为空，尝试从全局设备状态获取
        device_state_t *pdevice = get_device_state();
        if (strlen(pdevice->device_id) > 0) {
            Serial.println("从全局设备状态获取设备ID");
            device_id_to_use = pdevice->device_id;
        } else {
            Serial.println("设备ID为空，无法发送心跳包");
            http.end();
            return false;
        }
    }
    
    // 获取设备状态信息
    device_state_t *pdevice = get_device_state();
    
    // 读取最新的硬件状态
    // 注意：这里调用 read_all_hal() 函数来更新设备状态
    // 这个函数包含了对电池、温度和纸张状态的读取
    read_all_hal();
    
    // 获取WiFi信号强度
    int rssi = WiFi.RSSI();
    
    // 获取可用内存
    uint32_t freeHeap = ESP.getFreeHeap();
    uint32_t totalHeap = ESP.getHeapSize();
    float memoryUsage = 100.0 * (1.0 - ((float)freeHeap / totalHeap));
    
    // 获取设备运行时间（毫秒）
    unsigned long uptime = millis();
    
    // 准备请求体（添加更多的设备状态信息）
    String requestBody = "{";
    requestBody += "\"device_id\":\"" + String(device_id_to_use) + "\",";
    requestBody += "\"status\":\"online\",";
    requestBody += "\"wifi_status\":" + String(pdevice->wifi_state) + ",";
    requestBody += "\"bind_status\":" + String(pdevice->device_bind_state) + ",";
    requestBody += "\"signal_strength\":" + String(rssi) + ",";
    requestBody += "\"memory_usage\":" + String(memoryUsage, 2) + ",";
    requestBody += "\"free_heap\":" + String(freeHeap) + ",";
    requestBody += "\"uptime\":" + String(uptime) + ",";
    requestBody += "\"ip_address\":\"" + WiFi.localIP().toString() + "\",";
    
    // 添加打印机特有的状态信息
    requestBody += "\"printer_state\":" + String(pdevice->printer_state) + ",";
    requestBody += "\"paper_state\":" + String(pdevice->paper_state) + ",";
    requestBody += "\"paper_status\":\"" + String(pdevice->paper_state == PAPER_STATUS_NORMAL ? "正常" : "缺纸") + "\",";
    requestBody += "\"temperature\":" + String(pdevice->temperature) + ",";
    requestBody += "\"battery\":" + String(pdevice->battery) + ",";
    
    requestBody += "\"firmware_version\":\"1.0.0\"";
    requestBody += "}";
    
    Serial.print("心跳包请求体: ");
    Serial.println(requestBody);
    
    int httpResponseCode = http.POST(requestBody);
    
    Serial.print("心跳包HTTP响应码: ");
    Serial.println(httpResponseCode);
    
    if (httpResponseCode > 0) {
        String response = http.getString();
        Serial.println("心跳发送成功: " + response);
        http.end();
        return true;
    } else {
        Serial.print("心跳发送失败，错误码: ");
        Serial.println(httpResponseCode);
        http.end();
        return false;
    }
}

// 处理设备绑定
bool handle_device_binding(const char* server_url, const char* device_id) {
    if (!WifiManager.isConnected()) {
        Serial.println("WiFi未连接，无法绑定设备");
        return false;
    }

    http_device_bind_state = DEVICE_BINDING;
    
    // 检查并修正URL格式
    String url = String(server_url);
    if (!url.startsWith("http://") && !url.startsWith("https://")) {
        Serial.println("URL格式错误，自动添加http://前缀");
        url = "http://" + url;
    }
    
    Serial.print("处理设备绑定，服务器URL: ");
    Serial.println(url);
    Serial.print("设备ID: ");
    Serial.println(device_id);
    
    HTTPClient http;
    String apiUrl = url + "/api/printer/bind/";
    
    Serial.print("发送绑定请求到URL: ");
    Serial.println(apiUrl);
    
    bool beginResult = http.begin(apiUrl);
    if (!beginResult) {
        Serial.println("HTTP客户端初始化失败");
        return false;
    }
    
    http.addHeader("Content-Type", "application/json");
    
    // 准备请求体
    String requestBody = "{\"device_id\":\"";
    requestBody += device_id;
    requestBody += "\",\"device_type\":\"mini_printer\"}";
    
    Serial.print("请求体: ");
    Serial.println(requestBody);
    
    int httpResponseCode = http.POST(requestBody);
    
    Serial.print("HTTP响应码: ");
    Serial.println(httpResponseCode);
    
    if (httpResponseCode == 200) {
        String response = http.getString();
        Serial.println("设备绑定成功: " + response);
        http_device_bind_state = DEVICE_BINDED;
        
        // 更新HTTP模块的状态
        set_http_server_url(url.c_str());
        set_http_device_id(device_id);
        
        // 更新全局设备状态
        set_device_bind_status(DEVICE_BINDED);
        set_http_server_url(url.c_str());
        set_http_device_id(device_id);
        
        // 打印当前设备状态
        device_state_t *pdevice = get_device_state();
        
        // 再次确认全局状态已正确设置
        if (strlen(pdevice->server_url) == 0) {
            Serial.println("警告：全局设备状态中的服务器URL仍为空，手动设置");
            strcpy(pdevice->server_url, url.c_str());
        }
        
        if (strlen(pdevice->device_id) == 0) {
            Serial.println("警告：全局设备状态中的设备ID仍为空，手动设置");
            strcpy(pdevice->device_id, device_id);
        }
        
        Serial.print("全局设备状态 - 绑定状态: ");
        Serial.println(pdevice->device_bind_state == DEVICE_BINDED ? "已绑定" : "未绑定");
        Serial.print("全局设备状态 - 服务器URL: ");
        Serial.println(pdevice->server_url);
        Serial.print("全局设备状态 - 设备ID: ");
        Serial.println(pdevice->device_id);
        
        http.end();
        return true;
    } else {
        String response = http.getString();
        Serial.print("设备绑定失败，错误码: ");
        Serial.println(httpResponseCode);
        Serial.print("响应内容: ");
        Serial.println(response);
        http_device_bind_state = DEVICE_UNBINDED;
        http.end();
        return false;
    }
}

device_bind_state_e get_http_binding_state() {
    return http_device_bind_state;
}

void set_device_bind_state(device_bind_state_e state) {
    http_device_bind_state = state;
}

void set_http_server_url(const char* url) {
    strcpy(server_url, url);
}

const char* get_http_server_url() {
    return server_url;
}

void set_http_device_id(const char* id) {
    strcpy(device_id, id);
}

const char* get_http_device_id() {
    return device_id;
}

// 处理打印图片请求
void handlePrintImage() {
    Serial.println("收到打印图片请求");
    
    // 检查是否有请求体
    if (server.hasArg("plain") == false) {
        server.send(400, "text/plain", "未收到请求体数据");
        return;
    }
    
    // 获取请求体数据
    String data = server.arg("plain");
    Serial.print("收到的打印数据长度: ");
    Serial.println(data.length());
    
    // 检查Content-Type
    String contentType = server.header("Content-Type");
    Serial.print("Content-Type: ");
    Serial.println(contentType);
    
    // 尝试解析JSON，即使Content-Type不是application/json
    // 因为很多客户端可能发送JSON数据但不设置正确的Content-Type
    bool tryParseJson = true;
    
    if (contentType.indexOf("application/json") >= 0) {
        Serial.println("检测到JSON内容类型");
    } else {
        Serial.println("未检测到JSON内容类型，但仍尝试解析JSON");
    }
    
    if (tryParseJson) {
        // 尝试解析为JSON
        JsonDocument doc;
        DeserializationError error = deserializeJson(doc, data);
        
        if (error) {
            Serial.print("JSON解析失败: ");
            Serial.println(error.c_str());
            Serial.println("请求数据(前100个字符): ");
            if (data.length() > 100) {
                Serial.println(data.substring(0, 100) + "...");
            } else {
                Serial.println(data);
            }
            server.send(400, "text/plain", "JSON解析失败");
            return;
        }
        
        // 获取图像信息
        const char* device_id = doc["device_id"] | "";
        int width = doc["width"] | 0;
        int height = doc["height"] | 0;
        int bytes_per_line = doc["bytes_per_line"] | 0;
        const char* binary_base64 = doc["binary_data"] | "";
        
        // 打印图像信息到串口
        Serial.println("图像信息:");
        Serial.print("设备ID: ");
        Serial.println(device_id);
        Serial.print("宽度: ");
        Serial.println(width);
        Serial.print("高度: ");
        Serial.println(height);
        Serial.print("每行字节数: ");
        Serial.println(bytes_per_line);
        Serial.print("Base64数据长度: ");
        Serial.println(strlen(binary_base64));
        
        if (strlen(binary_base64) == 0) {
            Serial.println("错误: Base64数据为空");
            server.send(400, "text/plain", "Base64数据为空");
            return;
        }
        
        // 解码Base64数据
        int binary_data_len = base64_decoded_length(binary_base64);
        uint8_t* binary_data = (uint8_t*)malloc(binary_data_len);
        
        if (binary_data == NULL) {
            Serial.println("内存分配失败");
            server.send(500, "text/plain", "内存分配失败");
            return;
        }
        
        // 解码Base64编码的二进制数据
        base64_decode(binary_base64, binary_data);
        Serial.print("解码后的二进制数据长度: ");
        Serial.println(binary_data_len);
        
        // 确保数据长度是TPH_DI_LEN的倍数
        int paddedLength = ((binary_data_len + TPH_DI_LEN - 1) / TPH_DI_LEN) * TPH_DI_LEN;
        
        // 设置打印密度
        set_heat_density(100);
        
        // 打印数据
        Serial.println("开始打印图像数据...");
        start_printing(binary_data, binary_data_len);
        
        // 释放内存
        free(binary_data);
        
        Serial.println("打印完成");
        server.send(200, "text/plain", "打印成功");
    } else {
        // 不支持的内容类型
        Serial.println("不支持的内容类型");
        server.send(415, "text/plain", "不支持的内容类型，请使用 application/json");
    }
}

// Base64解码辅助函数
int base64_decoded_length(const char* encoded) {
    if (encoded == NULL) return 0;
    
    int len = strlen(encoded);
    int padding = 0;
    
    if (len > 0) {
        if (encoded[len - 1] == '=' && len > 1 && encoded[len - 2] == '=') {
            padding = 2;
        } else if (encoded[len - 1] == '=') {
            padding = 1;
        }
    }
    
    return (len * 3) / 4 - padding;
}

void base64_decode(const char* encoded, uint8_t* decoded) {
    if (encoded == NULL || decoded == NULL) return;
    
    const char* table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    int len = strlen(encoded);
    int i = 0, j = 0;
    
    while (i < len) {
        // 确保有足够的字符可以处理
        if (i + 3 >= len) break;
        
        // 在查找之前进行边界检查
        if (encoded[i] == '\0' || encoded[i + 1] == '\0') break;
        
        // 获取4个字符，查找在Base64表中的位置
        int a_pos = -1, b_pos = -1, c_pos = -1, d_pos = -1;
        char a_char = encoded[i];
        char b_char = encoded[i + 1];
        char c_char = (i + 2 < len) ? encoded[i + 2] : '=';
        char d_char = (i + 3 < len) ? encoded[i + 3] : '=';
        
        // 查找每个字符在表中的位置
        for(int k = 0; k < 64; k++) {
            if(table[k] == a_char) a_pos = k;
            if(table[k] == b_char) b_pos = k;
            if(c_char != '=' && table[k] == c_char) c_pos = k;
            if(d_char != '=' && table[k] == d_char) d_pos = k;
        }
        
        // 确保找到了有效的位置
        if(a_pos == -1 || b_pos == -1) break;
        
        // 将Base64编码值合并为二进制
        decoded[j++] = (a_pos << 2) | (b_pos >> 4);
        if (c_char != '=' && c_pos != -1) {
            decoded[j++] = (b_pos << 4) | (c_pos >> 2);
        }
        if (d_char != '=' && d_pos != -1) {
            decoded[j++] = (c_pos << 6) | d_pos;
        }
        
        i += 4;
    }
}

// 处理设备绑定请求
void handleDeviceBinding() {
    Serial.println("收到设备绑定请求");
    
    if (server.hasArg("plain") == false) {
        server.send(400, "text/plain", "Body not received");
        return;
    }
    
    String data = server.arg("plain");
    Serial.print("收到的绑定数据: ");
    Serial.println(data);
    
    // 检查Content-Type
    String contentType = server.header("Content-Type");
    Serial.print("Content-Type: ");
    Serial.println(contentType);
    
    String url;
    
    // 尝试解析JSON
    if (contentType.indexOf("application/json") >= 0 || data.indexOf("{") >= 0) {
        Serial.println("尝试解析JSON格式的绑定请求");
        
        JsonDocument doc;
        DeserializationError error = deserializeJson(doc, data);
        
        if (!error) {
            // JSON解析成功
            if (doc.containsKey("server_url")) {
                url = doc["server_url"].as<String>();
            }
        } else {
            Serial.print("JSON解析失败: ");
            Serial.println(error.c_str());
        }
    }
    
    // 如果JSON解析失败或者不是JSON格式，尝试老的格式
    if (url.length() == 0) {
        Serial.println("尝试解析旧格式的绑定请求");
        // 解析服务器URL
        int start = data.indexOf("server_url:") + 11;
        int end = data.indexOf(",", start);
        if (start > 11 && end > start) {
            url = data.substring(start, end);
        }
    }
    
    // 检查是否获取到URL
    if (url.length() > 0) {
        // 检查URL格式并修正
        if (!url.startsWith("http://") && !url.startsWith("https://")) {
            Serial.println("URL格式错误，自动添加http://前缀");
            url = "http://" + url;
        }
        
        Serial.print("解析后的服务器URL: ");
        Serial.println(url);
        
        // 设置HTTP模块的服务器URL和设备ID
        set_http_server_url(url.c_str());
        set_http_device_id(device_id);
        
        // 设置HTTP模块的设备绑定状态为已绑定
        set_device_bind_state(DEVICE_BINDED);
        
        // 更新全局设备状态 - 确保这些函数正确调用
        set_device_bind_status(DEVICE_BINDED);
        set_http_server_url(url.c_str());
        set_http_device_id(device_id);
        
        // 打印当前设备状态
        device_state_t *pdevice = get_device_state();
        
        // 再次确认全局状态已正确设置
        if (strlen(pdevice->server_url) == 0) {
            Serial.println("警告：全局设备状态中的服务器URL仍为空，手动设置");
            strcpy(pdevice->server_url, url.c_str());
        }
        
        if (strlen(pdevice->device_id) == 0) {
            Serial.println("警告：全局设备状态中的设备ID仍为空，手动设置");
            strcpy(pdevice->device_id, device_id);
        }
        
        Serial.print("全局设备状态 - 绑定状态: ");
        Serial.println(pdevice->device_bind_state == DEVICE_BINDED ? "已绑定" : "未绑定");
        Serial.print("全局设备状态 - 服务器URL: ");
        Serial.println(pdevice->server_url);
        Serial.print("全局设备状态 - 设备ID: ");
        Serial.println(pdevice->device_id);
        
        server.send(200, "text/plain", "设备绑定成功");
        Serial.println("设备绑定成功，服务器URL: " + url);
        Serial.println("设备绑定状态已更新为：已绑定");
    } else {
        Serial.println("无法解析服务器URL");
        server.send(400, "text/plain", "请求格式错误或缺少server_url字段");
    }
}

// 处理不存在的路径
void handleNotFound() {
    server.send(404, "text/plain", "找不到该路径");
}

void heartbeat_task_run() {
    device_state_t *pdevice = get_device_state();
    
    // 如果设备已绑定且WiFi已连接，则发送心跳包
    if (pdevice->device_bind_state == DEVICE_BINDED && 
        pdevice->wifi_state == WIFI_STATUS_CONNECTED) {
        
        unsigned long current_time = millis();
        
        // 检查是否到达发送心跳的时间
        if (current_time - last_heartbeat_time >= HEARTBEAT_INTERVAL || last_heartbeat_time == 0) {
            // 检查服务器URL是否有效
            if (strlen(pdevice->server_url) == 0) {
                Serial.println("服务器URL为空，无法发送心跳包");
                return;
            }
            
            Serial.print("准备发送心跳包，服务器URL: ");
            Serial.println(pdevice->server_url);
            
            // 发送心跳包
            if (send_heartbeat(pdevice->server_url)) {
                Serial.println("心跳包发送成功");
            } else {
                Serial.println("心跳包发送失败");
                
                // 检查WiFi连接状态
                if (WiFi.status() != WL_CONNECTED) {
                    Serial.println("WiFi连接已断开，尝试重新连接");
                    set_wifi_status(WIFI_STATUS_DISCONNECTED);
                    // 不在这里直接重连，让wifi_task_run处理
                }
            }
            
            // 更新上一次心跳时间
            last_heartbeat_time = current_time;
        }
    }
} 